Skip to content

fix(sonarcloud): declare all supported Python versions to Sonar - #92

Merged
williaby merged 1 commit into
mainfrom
claude/sonar-python-version-0
Sep 4, 2026
Merged

fix(sonarcloud): declare all supported Python versions to Sonar#92
williaby merged 1 commit into
mainfrom
claude/sonar-python-version-0

Conversation

@williaby

@williaby williaby commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Problem

sonar.python.version was 3.12, the single version CI builds with, while this project's
requires-python is ">=3.11,<3.15".

SonarPython gates version-specific rules on all declared versions:
PythonVersionUtils.areSourcePythonVersionsGreaterOrEqualThan is an allMatch. Declaring
only 3.12 therefore satisfies every >= 3.12 gate, so those rules fire against code that
must still run on 3.11.

This is not theoretical. SonarCloud currently reports 2 open issues in this repo from
python:S6794 / python:S6796, both urging PEP 695 type X = ... alias syntax. That syntax
is a SyntaxError on 3.11, which this project still supports. The rules are correct about
3.12; they are wrong about this project.

Fix

Declare the full range so allMatch(>= 3.12) is false and the 3.12-gated rules correctly
stay silent until the floor actually moves:

sonar-python-version: '3.11,3.12,3.13,3.14'

python-version stays 3.12. It feeds actions/setup-python and is the version the project
builds and tests with, which is a genuinely separate concern from the versions the source
must remain compatible with. Conflating the two is what caused this.

Why the pin moves too

sonar-python-version is new in ByronWilliamsCPA/.github#291 and does not exist in the
previously pinned revision. Passing an input the callee does not declare fails a reusable
workflow at startup, so the pin has to move to the commit that introduces it
(4bd2d7c, the squash commit of #291 on main).

Also in this change

sonar-project.properties is synced to the same list. CI overrides that key via
-Dsonar.python.version, so it has no effect on the pipeline, but SonarLint in the IDE
reads it
and would otherwise keep raising locally the exact false positives CI no longer
reports.

Verification

  • actionlint rc=0, yamllint clean
  • pre-commit run --all-files: every hook passes except pydoclint, which fails identically
    on untouched main (DOC105/109/110 in fuzz/*.py). This change touches no Python at all,
    so it is scoped out with SKIP=pydoclint rather than bypassed with --no-verify.

Expected result

The 2 open S6794/S6796 issues should clear on the next analysis. If they do not, the pin or
the input name is wrong and this should be reverted rather than papered over.

Note for maintainers

pydoclint is failing on main in this repo independently of this PR. Worth a separate fix.

Summary by CodeRabbit

  • Chores
    • Updated code quality analysis to support Python versions 3.11 through 3.14.
    • Refreshed the automated analysis workflow configuration.
    • Retained Python 3.12 as the build environment version.
    • Clarified Python version guidance for local analysis and SonarLint usage.
    • These updates improve consistency between automated checks and supported development environments without changing application functionality.

Copilot AI lite review requested due to automatic review settings August 6, 2026 04:05
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 1 package(s) with unknown licenses.
See the Details below.

License Issues

.github/workflows/sonarcloud.yml

PackageVersionLicenseIssue Type
ByronWilliamsCPA/.github/.github/workflows/python-sonarcloud.yml4bd2d7c207a7fcf2dfcec8416c805d06d745c241NullUnknown License
Denied Licenses: GPL-2.0, GPL-3.0

OpenSSF Scorecard

PackageVersionScoreDetails
actions/ByronWilliamsCPA/.github/.github/workflows/python-sonarcloud.yml 4bd2d7c207a7fcf2dfcec8416c805d06d745c241 UnknownUnknown

Scanned Files

  • .github/workflows/sonarcloud.yml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes SonarCloud and SonarLint false positives by declaring the full set of Python versions the source code must support, aligned with requires-python (>=3.11,<3.15), rather than only the single CI build version.

Changes:

  • Update sonar-project.properties to set sonar.python.version=3.11,3.12,3.13,3.14 for accurate local and IDE (SonarLint) analysis.
  • Update the SonarCloud reusable workflow pin to a revision that supports the new sonar-python-version input.
  • Pass sonar-python-version: '3.11,3.12,3.13,3.14' to SonarCloud while keeping python-version: '3.12' for CI runtime.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
sonar-project.properties Aligns sonar.python.version with the project’s supported Python range for correct local and SonarLint analysis.
.github/workflows/sonarcloud.yml Passes the supported Python version range to SonarCloud and updates the reusable workflow pin to a compatible revision.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: e9acae52-c9b2-41ab-b1e4-725bc1ebcc21

📥 Commits

Reviewing files that changed from the base of the PR and between a5fc0f6 and d533a29.

📒 Files selected for processing (1)
  • .github/workflows/sonarcloud.yml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

SonarCloud configuration now analyzes Python 3.11 through 3.14. The workflow keeps Python 3.12 as the build version and uses an updated reusable workflow revision.

Changes

SonarCloud Python version support

Layer / File(s) Summary
Configure multi-version SonarCloud analysis
.github/workflows/sonarcloud.yml, sonar-project.properties
The workflow and SonarCloud properties target Python 3.11, 3.12, 3.13, and 3.14. Comments document the relationship to requires-python, CI overrides, and SonarLint. The reusable workflow reference is updated.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk: ⚪ Minimal · up to d533a

This updates Sonar analysis to cover supported Python versions 3.11 through 3.14 without changing the CI runtime version. No concrete merge-blocking risk remains.

Suggested reviewers: byronwilliamscpa

Poem

A rabbit checked the versions in a row,
“Three-eleven through three-fourteen, go!”
The build stays three-twelve,
Sonar scans them all,
And clean reports begin to grow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: configuring SonarCloud to recognize all supported Python versions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/sonar-python-version-0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added ci documentation Improvements or additions to documentation labels Aug 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/sonarcloud.yml:
- Line 32: Update the python-sonarcloud reusable workflow checkout to disable
credential persistence by configuring its checkout step with persist-credentials
set to false. Alternatively, update the pinned reusable-workflow revision to one
that already applies this setting, while preserving the existing workflow
permissions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d04ae5a2-393f-438b-839a-f6b15bc61b4d

📥 Commits

Reviewing files that changed from the base of the PR and between a06abe3 and a5fc0f6.

📒 Files selected for processing (2)
  • .github/workflows/sonarcloud.yml
  • sonar-project.properties

sonarcloud:
name: SonarCloud Analysis
uses: ByronWilliamsCPA/.github/.github/workflows/python-sonarcloud.yml@74c633acfdd5f707ab154fd59bd212c6df663dd6 # main
uses: ByronWilliamsCPA/.github/.github/workflows/python-sonarcloud.yml@4bd2d7c207a7fcf2dfcec8416c805d06d745c241 # main

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository workflow =="
git ls-files .github/workflows/sonarcloud.yml || true
if [ -f .github/workflows/sonarcloud.yml ]; then
  nl -ba .github/workflows/sonarcloud.yml | sed -n '1,220p'
fi

echo
echo "== available git references for pinned reusable workflow =="
git ls-remote --heads --tags https://github.com/ByronWilliamsCPA/.github.git 4bd2d7c207a7fcf2dfcec8416c805d06d745c241 || true
git ls-remote https://github.com/ByronWilliamsCPA/.github.git main || true

echo
echo "== raw reusable workflow around checkout and job permissions =="
python3 - <<'PY'
import urllib.request
pinned = "4bd2d7c207a7fcf2dfcec8416c805d06d745c241"
url = f"https://raw.githubusercontent.com/ByronWilliamsCPA/.github/{pinned}/.github/workflows/python-sonarcloud.yml"
try:
    with urllib.request.urlopen(url, timeout=20) as r:
        data = r.read().decode()
    lines = data.splitlines()
    for i, line in enumerate(lines, 1):
        if "actions/checkout" in line or "permissions:" in line or "pull-requests:" in line or "sonar-python-version" in line:
            start=max(1,i-8); end=min(len(lines), i+10)
            print(f"--- matches line {i} range {start}-{end} ---")
            for j in range(start, end+1):
                print(f"{j:4}: {lines[j-1]}")
except Exception as e:
    print(f"ERROR fetching {url}: {e.__class__.__name__}: {e}")
PY

echo
echo "== checkout input defaults around persist-credentials =="
python3 - <<'PY'
import urllib.request
base = "https://raw.githubusercontent.com/actions/checkout"
for ref in ["v4", "main", "9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0"]:
    try:
        url = f"{base}/{ref}/action.yml"
        data = urllib.request.urlopen(url, timeout=20).read().decode()
        lines = data.splitlines()
        print(f"--- action.yml {ref} ---")
        for i,line in enumerate(lines,1):
            if "persist-credentials" in line:
                print(f"{i:4}: {line}")
    except Exception as e:
        print(f"ERROR for checkout {ref}: {e}")
PY

Repository: ByronWilliamsCPA/rag-processor

Length of output: 267


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== check workflow trigger and job contents =="
nl -ba .github/workflows/sonarcloud.yml | sed -n '1,220p'

echo
echo "== resolve exact reusable workflow workflow file by git API =="
git ls-remote https://github.com/ByronWilliamsCPA/.github.git 4bd2d7c207a7fcf2dfcec8416c805d06d745c241 || true
git ls-remote https://github.com/ByronWilliamsCPA/.github.git refs/tags/main || true
git ls-remote https://github.com/ByronWilliamsCPA/.github.git refs/heads/main || true

Repository: ByronWilliamsCPA/rag-processor

Length of output: 254


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository workflow =="
awk '{printf "%5d: %s\n", NR, $0}' .github/workflows/sonarcloud.yml | sed -n '1,220p'

echo
echo "== raw reusable workflow around checkout, permissions, and inputs =="
python3 - <<'PY'
import urllib.request
pinned = "4bd2d7c207a7fcf2dfcec8416c805d06d745c241"
url = f"https://raw.githubusercontent.com/ByronWilliamsCPA/.github/{pinned}/.github/workflows/python-sonarcloud.yml"
try:
    with urllib.request.urlopen(url, timeout=20) as r:
        data = r.read().decode()
except Exception as e:
    print(f"ERROR fetching {url}: {e.__class__.__name__}: {e}")
    raise SystemExit(1)
lines = data.splitlines()
for i, line in enumerate(lines, 1):
    if any(k in line for k in ("actions/checkout", "permissions:", "'pull-requests:', 'pull-requests:", "pull-requests:", "sonar-python-version", "GITHUB_TOKEN", "GITHUB_OUTPUT")):
        print(f"--- matches line {i} ---")
        for j in range(max(1, i-8), min(len(lines), i+10)+1):
            print(f"{j:4}: {lines[j-1]}")

echo
echo "== checkout persist-credentials input description from action.yml =="
python3 - <<'PY'
import urllib.request
base = "https://raw.githubusercontent.com/actions/checkout"
for ref in ["v4"]:
    try:
        data = urllib.request.urlopen(f"{base}/{ref}/action.yml", timeout=20).read().decode()
        print(f"--- {ref} ---")
        for i, line in enumerate(data.splitlines(), 1):
            if "persist-credentials" in line or line.strip() == "description:":
                print(f"{i:4}: {line}")
    except Exception as e:
        print(f"ERROR checkout {ref}: {e}")
PY

Repository: ByronWilliamsCPA/rag-processor

Length of output: 2359


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== raw reusable workflow around sensitive lines =="
python3 - <<'PY'
import urllib.request
pinned = "4bd2d7c207a7fcf2dfcec8416c805d06d745c241"
url = f"https://raw.githubusercontent.com/ByronWilliamsCPA/.github/{pinned}/.github/workflows/python-sonarcloud.yml"
try:
    lines = urllib.request.urlopen(url, timeout=20).read().decode().splitlines()
except Exception as e:
    print(f"ERROR fetching {url}: {e.__class__.__name__}: {e}")
else:
    for i, line in enumerate(lines, 1):
        if "actions/checkout" in line or "GITHUB_TOKEN" in line or "pull-requests" in line or "sonar-python-version" in line or "uv sync" in line or "pytest" in line or "GH_TOKEN" in line:
            start=max(1,i-10); end=min(len(lines), i+12)
            print(f"--- matches line {i} range {start}-{end} ---")
            for j in range(start, end+1):
                print(f"{j:4}: {lines[j-1]}")

echo
echo "== GitHub action checkout persist-credentials from v4 == "
python3 - <<'PY'
import urllib.request
data = urllib.request.urlopen("https://raw.githubusercontent.com/actions/checkout/v4/action.yml", timeout=20).read().decode()
for i, line in enumerate(data.splitlines(), 1):
    if "persist-credentials" in line:
        print(f"{i:4}: {line}")
PY

Repository: ByronWilliamsCPA/rag-processor

Length of output: 353


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== reusable workflow relevant sections =="
python3 - <<'PY'
import urllib.request
sha = "4bd2d7c207a7fcf2dfcec8416c805d06d745c241"
url = f"https://raw.githubusercontent.com/ByronWilliamsCPA/.github/{sha}/.github/workflows/python-sonarcloud.yml"
try:
    text = urllib.request.urlopen(url, timeout=20).read().decode()
except Exception as e:
    print(f"ERROR fetching {url}: {e.__class__.__name__}: {e}")
    raise SystemExit(1)
lines = text.splitlines()
keywords = ["actions/checkout", "persist-credentials", "GITHUB_TOKEN", "pull-requests", "uv sync", "pytest", "sonar-python-version", "GH_TOKEN"]
for i, line in enumerate(lines, 1):
    if any(k in line for k in keywords):
        start=max(1,i-10); end=min(len(lines), i+12)
        print(f"--- matches line {i} range {start}-{end} ---")
        for j in range(start, end+1):
            print(f"{j:4}: {lines[j-1]}")
PY

echo
echo "== actions/checkout persist-credentials reference from v4 =="
python3 - <<'PY'
import urllib.request
text = urllib.request.urlopen("https://raw.githubusercontent.com/actions/checkout/v4/action.yml", timeout=20).read().decode()
for i, line in enumerate(text.splitlines(), 1):
    if "persist-credentials" in line:
        print(f"{i:4}: {line}")
PY

Repository: ByronWilliamsCPA/rag-processor

Length of output: 511


🌐 Web query:

GitHub actions checkout v4 persist-credentials default true action.yml

💡 Result:

In the official action.yml configuration for the GitHub Actions checkout action, the default value for the persist-credentials input is true [1][2]. When persist-credentials is set to its default value (true), the authentication token or SSH key used to clone the repository is configured in the local Git configuration. This allows subsequent scripts in your workflow job to run authenticated Git commands [3][4]. The token is automatically removed during the post-job cleanup phase [3][2]. If you wish to opt out of this behavior—for example, to prevent the credential from being stored in the local Git configuration—you can explicitly set persist-credentials to false in your workflow file [3][4]. While there have been community discussions and pull requests proposing to change this default to false for security hardening [5], it remains true in the official v4 and v6 releases of the action [1][6].

Citations:


Sensitive Data Exposure (CWE-522): Insufficiently Protected Credentials

Reachability: Internal

Disable persisted credentials in the reusable workflow checkout.

This job grants pull-requests: write before the pinned reusable workflow checkout persists GITHUB_TOKEN in Git credentials by default. This token remains available until post-job cleanup. Set persist-credentials: false on the checkout step in ByronWilliamsCPA/.github/.github/workflows/python-sonarcloud.yml, or pin a reusable-workflow revision that already disables it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sonarcloud.yml at line 32, Update the python-sonarcloud
reusable workflow checkout to disable credential persistence by configuring its
checkout step with persist-credentials set to false. Alternatively, update the
pinned reusable-workflow revision to one that already applies this setting,
while preserving the existing workflow permissions.

Sources: Coding guidelines, Path instructions, Learnings, MCP tools

@williaby
williaby enabled auto-merge September 3, 2026 12:33
@williaby
williaby force-pushed the claude/sonar-python-version-0 branch from a5fc0f6 to d533a29 Compare September 3, 2026 21:07
@coderabbitai coderabbitai Bot removed ci documentation Improvements or additions to documentation labels Sep 3, 2026
sonar.python.version was 3.12, the single version CI builds with, while
requires-python is ">=3.11,<3.15". SonarPython gates version-specific rules on
ALL declared versions (PythonVersionUtils.areSourcePythonVersionsGreaterOrEqualThan
is allMatch), so declaring only 3.12 made every 3.12-gated rule fire against code
that must still run on 3.11.

That produced 2 live false positives today: S6794 and S6796 urging PEP 695
"type X = ..." aliases, which are a SyntaxError on 3.11. Declaring the full range
makes allMatch(>=3.12) false, so the rules correctly stay silent until the floor
moves.

Sets the new sonar-python-version input (ByronWilliamsCPA/.github#291) and bumps
the uses: pin to the commit that introduces it, since the input does not exist in
the previously pinned revision and passing an undefined input fails the reusable
workflow at startup.

Also syncs sonar-project.properties. CI overrides that key via -D, so it does not
affect the pipeline, but SonarLint in the IDE reads it and would otherwise keep
raising the same false positives locally that CI no longer reports.

python-version stays 3.12: it feeds actions/setup-python and is the version the
project builds and runs tests with, which is a separate concern from the versions
the source must remain compatible with.

Pre-commit: all hooks pass except pydoclint, which fails identically on untouched
main (DOC105/109/110 in fuzz/*.py). This change touches no Python, so it is
scoped out with SKIP=pydoclint rather than bypassed.
@williaby
williaby force-pushed the claude/sonar-python-version-0 branch from d533a29 to ca394e4 Compare September 4, 2026 15:34
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

@williaby
williaby added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit 6bc3d59 Sep 4, 2026
47 checks passed
@williaby
williaby deleted the claude/sonar-python-version-0 branch September 4, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants